package com.es.highLevel;

import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequest;
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.RepositoryMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.*;
import org.elasticsearch.snapshots.SnapshotInfo;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class SnapshotTest {

    public static void main(String[] args) throws IOException {
        RestHighLevelClient client = HighLevelClientTest.createClient();
        //createRepository(client, "product_info");
        //createRepository(client, "src/main/resources/productInfo.json", "product_info");
        createSnapshot(client, "product_info","product_info", "product_info");
        //deleteSnapshot(client, "product_info");
        restoreSnapshot(client, "product_info", "product_info", "product_info");
    }

    /**
     * 创建仓库
     */
    public static void createRepository(RestHighLevelClient client, String repositoryName) {
        GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest(new String[]{repositoryName});
        boolean hasRepository = false;
        try {
            GetRepositoriesResponse repository = client.snapshot().getRepository(getRepositoriesRequest, RequestOptions.DEFAULT);
            List<RepositoryMetaData> repositories = repository.repositories();
            for (RepositoryMetaData repositoryMetadata : repositories) {
                if(repositoryMetadata.name().equals(repositoryName)){
                    hasRepository = true;
                    break;
                }
            }
        } catch (ElasticsearchStatusException ee) {
            System.out.println("仓库不存在：" + ee.getMessage());
        } catch (IOException ioException) {
            // 客户端版本略低，所以用异常捕获方式判断，索引存在会抛到这里异常
            System.err.println(ioException.getMessage());
            hasRepository = true;
        }
        if(!hasRepository){
            try {
                PutRepositoryRequest repositoryRequest = new PutRepositoryRequest();
                repositoryRequest.name(repositoryName);
                repositoryRequest.verify(false);
                repositoryRequest.name(repositoryName);
                repositoryRequest.type("fs");
                repositoryRequest.settings(Settings.builder().put("location", "/data/esbackup/productInfo"));
                AcknowledgedResponse acknowledgedResponse = client.snapshot().createRepository(repositoryRequest, RequestOptions.DEFAULT);
                if (acknowledgedResponse.isAcknowledged()) {
                    System.out.println("创建仓库成功: " + repositoryName);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            client.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建仓库
     */
    public static void createRepository(RestHighLevelClient client, String settingPath, String repositoryName) {
        GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest(new String[]{repositoryName});
        boolean hasRepository = false;
        try {
            GetRepositoriesResponse repository = client.snapshot().getRepository(getRepositoriesRequest, RequestOptions.DEFAULT);
            List<RepositoryMetaData> repositories = repository.repositories();
            for (RepositoryMetaData repositoryMetadata : repositories) {
                if(repositoryMetadata.name().equals(repositoryName)){
                    hasRepository = true;
                    break;
                }
            }
        } catch (ElasticsearchStatusException ee) {
            System.out.println("仓库不存在：" + ee.getMessage());
        } catch (IOException ioException) {
            // 客户端版本略低，所以用异常捕获方式判断，索引存在会抛到这里异常
            System.err.println(ioException.getMessage());
            hasRepository = true;
        }
        if(!hasRepository){
            try {
                String jsonString = new String(Files.readAllBytes(Paths.get(settingPath)), StandardCharsets.UTF_8);
                // 解析 json
                PutRepositoryRequest repositoryRequest = new PutRepositoryRequest();
                XContentParser contentParser = XContentFactory.xContent(XContentType.JSON).createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, jsonString);
                repositoryRequest.name(repositoryName);
                repositoryRequest.verify(false);
                repositoryRequest.source(contentParser.map());
                AcknowledgedResponse acknowledgedResponse = client.snapshot().createRepository(repositoryRequest, RequestOptions.DEFAULT);
                if (acknowledgedResponse.isAcknowledged()) {
                    System.out.println("创建仓库成功: " + repositoryName);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            client.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成快照
     */
    public static boolean createSnapshot(RestHighLevelClient client, String snapshotName, String repositoryName, String... indexes) {
        CreateSnapshotRequest createSnapshotRequest = new CreateSnapshotRequest();
        createSnapshotRequest.indices(indexes);
        createSnapshotRequest.snapshot(snapshotName);
        createSnapshotRequest.repository(repositoryName);
        createSnapshotRequest.waitForCompletion(true);
        createSnapshotRequest.includeGlobalState(false);
        try {
            CreateSnapshotResponse snapshotResponse = client.snapshot().create(createSnapshotRequest, RequestOptions.DEFAULT);
            SnapshotInfo snapshotInfo = snapshotResponse.getSnapshotInfo();
            if (snapshotInfo.status().getStatus() == 200) {
                System.out.println("快照创建成功：" + snapshotInfo);
                return true;
            }
        } catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return false;
    }

    /**
     * 恢复快照
     */
    public static void restoreSnapshot(RestHighLevelClient client, String snapshotName, String repositoryName, String indexes){
        RestoreSnapshotRequest restoreSnapshotRequest = new RestoreSnapshotRequest();
        restoreSnapshotRequest.snapshot(snapshotName);
        restoreSnapshotRequest.repository(repositoryName);
        restoreSnapshotRequest.indices(indexes);
        try {
            RestoreSnapshotResponse restoreSnapshotResponse = client.snapshot().restore(restoreSnapshotRequest, RequestOptions.DEFAULT);
            System.out.println("快照恢复成功：" + restoreSnapshotResponse.getRestoreInfo().toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 删除快照
     */
    public static boolean deleteSnapshot(RestHighLevelClient client, String repositoryName) {
        DeleteSnapshotRequest deleteSnapshotRequest = new DeleteSnapshotRequest();
        deleteSnapshotRequest.snapshot(repositoryName);
        deleteSnapshotRequest.repository(repositoryName);
        try {
            AcknowledgedResponse deleteSnapshotResponse = client.snapshot().delete(deleteSnapshotRequest, RequestOptions.DEFAULT);
            if (deleteSnapshotResponse.isAcknowledged()) {
                System.out.println("快照删除成功！");
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return false;
    }

}
